﻿using System;
using DatabaseGroup.SSIS.SourceAdapters.View;
using DatabaseGroup.SSIS.SourceAdapters.Model;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

namespace DatabaseGroup.SSIS.SourceAdapters.Presenter
{
    /// <summary>
    /// Presenter for handling the Audit tab view
    /// </summary>
    public class AuditTabPresenter
    {
        private readonly IEditorAuditView _view;
        private readonly IComponentModel _model;
        private AuditTabSettings _settings;

        /// <summary>
        /// Initializes a new instance of the AuditTabPresenter class
        /// using the view and propertiesModel
        /// </summary>
        /// <param name="view">An instance of an IEditorAuditView</param>
        /// <param name="model">An instance of an IComponentModel</param>
        public AuditTabPresenter(IEditorAuditView view, IComponentModel model)
        {
            _view = view;
            _model = model;

            InitializeView();

            view.ViewSettings += view_ViewSettings;
            view.SavingSettings += view_SavingSettings;
            view.LogSourceDataTypeUpdated += view_LogSourceDataTypeUpdated;
            view.ErrorSourceDataTypeUpdated += view_ErrorSourceDataTypeUpdated;
        }

        /// <summary>
        /// Updates the error output source data size based on the datatype being used
        /// </summary>
        /// <param name="sender">The View</param>
        /// <param name="e"></param>
        private void view_ErrorSourceDataTypeUpdated(object sender, EventArgs e)
        {
            RefreshErrorSourceSize();
        }

        /// <summary>
        /// Updates the log output source data size based on the datatype being used
        /// </summary>
        /// <param name="sender">The View</param>
        /// <param name="e"></param>
        private void view_LogSourceDataTypeUpdated(object sender, EventArgs e)
        {
            RefreshLogSourceSize();
        }

        /// <summary>
        /// Binds the view with the current settings object
        /// </summary>
        /// <param name="sender">The View</param>
        /// <param name="e"></param>
        private void view_ViewSettings(object sender, TabEventArgs e)
        {
            if (e.Tab != EditorViewTab.Auditing && e.Tab != EditorViewTab.ANY)
                return;

            _view.BindAuditTab(_settings);
            RefreshErrorSourceSize();
            RefreshLogSourceSize();
        }

        /// <summary>
        /// Saves the current settings to the component metadata
        /// </summary>
        /// <param name="sender">The View</param>
        /// <param name="e"></param>
        private void view_SavingSettings(object sender, EventArgs e)
        {
            _model.SetProperty(PropertiesManager.IncludeLogOutputPropName, _settings.IncludeLogOutput);
            _model.SetProperty(PropertiesManager.IncludeValidationMessagesPropName, _settings.IncludeLogValidationMessages);
            _model.SetProperty(PropertiesManager.IncludeLogSourceDataPropName, _settings.IncludeLogSourceData);
            _model.SetProperty(PropertiesManager.LogSourceDataTypePropName, Enum.Parse(typeof(DataType), _settings.LogSourceDataType));
            _model.SetProperty(PropertiesManager.LogSourceDataSizePropName, _settings.LogSourceDataSize);

            _model.SetProperty(PropertiesManager.IncludeErrorAuditRowsPropName, _settings.IncludeErrorAuditing);
            _model.SetProperty(PropertiesManager.IncludeErrorValidationMessagesPropName, _settings.IncludeErrorValidationMessages);
            _model.SetProperty(PropertiesManager.IncludeErrorSourceDataPropName, _settings.IncludeErrorSourceData);
            _model.SetProperty(PropertiesManager.ErrorSourceDataTypePropName, Enum.Parse(typeof(DataType), _settings.ErrorSourceDataType));
            _model.SetProperty(PropertiesManager.ErrorSourceDataSizePropName, _settings.ErrorSourceDataSize);

            _model.ReconfigureErrorOutput();
            _model.SetupLogOutput();
        }

        /// <summary>
        /// Updates the error source data size based on the datatype being used
        /// </summary>
        private void RefreshErrorSourceSize()
        {
            DataType errorSourceDataType = (DataType)Enum.Parse(typeof(DataType), _settings.ErrorSourceDataType);

            if (errorSourceDataType == DataType.DT_TEXT || errorSourceDataType == DataType.DT_NTEXT)
                _view.SetErrorSourceSizeAvailability(false);
            else
                _view.SetErrorSourceSizeAvailability(true);
        }

        /// <summary>
        /// Updates the log source data size based on the datatype being used
        /// </summary>
        private void RefreshLogSourceSize()
        {
            DataType logSourceDataType = (DataType)Enum.Parse(typeof(DataType), _settings.LogSourceDataType);

            if (logSourceDataType == DataType.DT_TEXT || logSourceDataType == DataType.DT_NTEXT)
                _view.SetLogSourceSizeAvailability(false);
            else
                _view.SetLogSourceSizeAvailability(true);
        }

        /// <summary>
        /// Creates a new audit settings object and loads it with the current
        /// component configuration and binds it to the view
        /// </summary>
        private void InitializeView()
        {
            _settings = new AuditTabSettings();

            _settings.IncludeLogOutput = _model.GetProperty<bool>(PropertiesManager.IncludeLogOutputPropName);
            _settings.IncludeLogValidationMessages = _model.GetProperty<bool>(PropertiesManager.IncludeValidationMessagesPropName);
            _settings.IncludeLogSourceData = _model.GetProperty<bool>(PropertiesManager.IncludeLogSourceDataPropName);
            _settings.LogSourceDataType =
                Enum.GetName(typeof(DataType), _model.GetProperty<DataType>(PropertiesManager.LogSourceDataTypePropName));
            _settings.LogSourceDataSize = _model.GetProperty<int>(PropertiesManager.LogSourceDataSizePropName);

            _settings.IncludeErrorAuditing = _model.GetProperty<bool>(PropertiesManager.IncludeErrorAuditRowsPropName);
            _settings.IncludeErrorValidationMessages = _model.GetProperty<bool>(PropertiesManager.IncludeErrorValidationMessagesPropName);
            _settings.IncludeErrorSourceData = _model.GetProperty<bool>(PropertiesManager.IncludeErrorSourceDataPropName);
            _settings.ErrorSourceDataType =
                Enum.GetName(typeof(DataType), _model.GetProperty<DataType>(PropertiesManager.ErrorSourceDataTypePropName));
            _settings.ErrorSourceDataSize = _model.GetProperty<int>(PropertiesManager.ErrorSourceDataSizePropName);

            _view.BindAuditTab(_settings);
        }
    }
}
